package com.gqz.patrol.app.service.impl;

import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.exceptions.ExceptionUtil;
import cn.hutool.core.util.BooleanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.gqz.patrol.app.entity.EnPatrolTaskEntity;
import com.gqz.patrol.app.entity.EnPatrolTaskEquipEntity;
import com.gqz.patrol.app.entity.EnPatrolTaskOperateEntity;
import com.gqz.patrol.app.entity.EnPatrolTaskPeriodEntity;
import com.gqz.patrol.app.entity.po.PatrolTaskPo;
import com.gqz.patrol.app.mapper.EnPatrolTaskEquipMapper;
import com.gqz.patrol.app.mapper.EnPatrolTaskMapper;
import com.gqz.patrol.app.mapper.EnPatrolTaskOperateMapper;
import com.gqz.patrol.app.mapstruct.EnPatrolTaskEquipMapstruct;
import com.gqz.patrol.app.mapstruct.EnPatrolTaskMapstruct;
import com.gqz.patrol.app.service.IEnPatrolTaskOperateService;
import com.gqz.patrol.app.service.IEnPatrolTaskPeriodService;
import com.gqz.patrol.app.service.IPatorlEnWzJfEquipService;
import com.gqz.patrol.app.service.MqEnPatrolTaskService;
import com.gqz.patrol.app.utils.PeriodEnum;
import com.gqz.patrol.vo.EnPatrolTaskVo;
import jakarta.annotation.Resource;
import org.apache.commons.beanutils.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Optional;

/**
 * @ClassName MqEnPatrolTaskServiceImpl
 * @Description 能源--巡视任务
 */
@Service
public class MqEnPatrolTaskServiceImpl extends ServiceImpl<EnPatrolTaskMapper, EnPatrolTaskEntity> implements MqEnPatrolTaskService {


    @Resource
    private EnPatrolTaskMapstruct patrolTaskMapstruct;

    @Resource
    private EnPatrolTaskEquipMapstruct taskEquipMapstruct;

    @Resource
    private EnPatrolTaskEquipServiceImpl taskEquipService;

    @Autowired
    private IEnPatrolTaskPeriodService taskPeriodService;

    @Resource
    private IPatorlEnWzJfEquipService wzJfEquipService;

    @Resource
    private EnPatrolTaskMapstruct mapstruct;

    @Resource
    private EnPatrolTaskOperateMapper taskOperateMapper;
    @Autowired
    private IEnPatrolTaskOperateService taskOperateService;

    @Resource
    private EnPatrolTaskEquipMapper equipMapper;

    /**
     * 派单
     *
     * @param vo vo
     * @return
     */
    @Override
    public int sendOrder(EnPatrolTaskVo vo) {
        EnPatrolTaskEntity patrolTaskEntity = this.patrolTaskMapstruct.toEntity(vo);
        patrolTaskEntity.setPTaskStatusNo("10");
        patrolTaskEntity.setPTaskStatusName("已派单");
        patrolTaskEntity.setATaskStatusNo("1");
        patrolTaskEntity.setATaskStatusName("待办");

        LambdaQueryWrapper<EnPatrolTaskEntity> updateWrapper = new LambdaQueryWrapper<>();
        updateWrapper.eq(EnPatrolTaskEntity::getTaskNo, vo.getTaskNo());
        this.baseMapper.update(patrolTaskEntity, updateWrapper);
        return 1;
    }

    /**
     * 新增巡视工单，通过两张表的方式
     *
     * @param vos
     * @return
     */
    @Override
    @Transactional
    public List<String> insertV2(List<EnPatrolTaskVo> vos) {
        List<EnPatrolTaskEntity> inputs = patrolTaskMapstruct.toEntitys(vos);

        ArrayList<EnPatrolTaskEntity> taskEntities = new ArrayList<>();
        ArrayList<EnPatrolTaskEquipEntity> taskEquipEntities = new ArrayList<>();
        //周期记录
        ArrayList<EnPatrolTaskPeriodEntity> taskPeriodEntities = new ArrayList<>();
        ArrayList<EnPatrolTaskOperateEntity> taskOperateEntities = new ArrayList<>();

        inputs.forEach(vo -> {
            String taskNo = vo.getTaskNo();
            Optional.ofNullable(taskNo).orElseThrow(() -> new RuntimeException("巡视工单编号不可为空！"));
            String taskName = vo.getTaskName();
            // 周期截止日期
            Date periodEtime = vo.getPeriodEndTime();
            // 初始计划开始时间
            Date planStime = vo.getPlanStartTime();
            // 初始计划结束时间
            Date planEtime = vo.getPlanEndTime();
            //工单类型
            String taskTypeNo = vo.getPatrolTypeNo();
            //设置源工单编码
            vo.setSourceTaskNo(taskNo);
            //设置工单来源
            vo.setTaskSourceNo("1");

            EnPatrolTaskOperateEntity operateEntity = new EnPatrolTaskOperateEntity();
            operateEntity.setTaskNo(taskNo);
            operateEntity.setOptStatus("0");
            operateEntity.setOptStatusName("工单编制");
            operateEntity.setOptTime(new Date());
            taskOperateEntities.add(operateEntity);
            //非周期性工单
            if ("2".equals(taskTypeNo)) {
                vo.setIsPeriod("0");
                taskEntities.add(vo);
            }
            //周期性工单
            if ("1".equals(taskTypeNo)) {
                if (DateUtil.compare(planStime, planEtime) >= 0 || DateUtil.compare(periodEtime, planEtime) < 0) {
                    ExceptionUtil.wrapRuntimeAndThrow("计划结束时间不可比计划开始时间早或者周期结束时间不可小于计划结束时间!");
                }
                vo.setIsPeriod("1");
                // 周期天数
                int period = Integer.parseInt(vo.getPeriod());
                // 周期内总天数
                long dayNum = DateUtil.between(planStime, periodEtime, DateUnit.DAY);

                EnPatrolTaskPeriodEntity taskPeriodEntity = new EnPatrolTaskPeriodEntity();
                try {
                    BeanUtils.copyProperties(taskPeriodEntity, vo);
                } catch (IllegalAccessException | InvocationTargetException e) {
                    throw new RuntimeException(e);
                }
                taskPeriodEntity.setExecutePeriodNum("2");
                taskPeriodEntity.setExecuteStime(DateUtil.offsetDay(planStime, period));
                taskPeriodEntity.setExecuteEtime(DateUtil.offsetDay(planEtime, period));
                taskPeriodEntity.setCreatTime(DateUtil.now());
                // taskPeriodEntity.setExecuteTaskNo(GenTaskNoTool.createTaskNo());

                vo.setTaskName(taskName + "-周期内-" + 1);

                taskEntities.add(vo);
                taskPeriodEntities.add(taskPeriodEntity);
            }
            //电能表巡视
            if ("3".equals(taskTypeNo)) {
                if (DateUtil.compare(planStime, planEtime) >= 0 || DateUtil.compare(periodEtime, planEtime) < 0) {
                    ExceptionUtil.wrapRuntimeAndThrow("计划结束时间不可比计划开始时间早或者周期结束时间不可小于计划结束时间!");
                }
                vo.setIsPeriod("1");
                // 周期天数 周期固定
                String period = vo.getPeriod();
                PeriodEnum periodEnum = PeriodEnum.valueOf(period.toUpperCase());

                Date exeSTime = null;
                Date exeETime = null;
                switch (periodEnum) {
                    case WEEK:
                        exeSTime = DateUtil.offsetWeek(planStime, 1);
                        exeETime = DateUtil.offsetWeek(planEtime, 1);
                        break;
                    case MONTH:
                        exeSTime = DateUtil.offsetMonth(planStime, 1);
                        exeETime = DateUtil.offsetMonth(planEtime, 1);
                        break;
                    case QUARTER:
                        exeSTime = DateUtil.offsetMonth(planStime, 3);
                        exeETime = DateUtil.offsetMonth(planEtime, 3);
                        break;
                    default:
                        ExceptionUtil.wrapRuntimeAndThrow("输入的周期不在可选范围内");
                        break;
                }
                EnPatrolTaskPeriodEntity taskPeriodEntity = new EnPatrolTaskPeriodEntity();
                try {
                    BeanUtils.copyProperties(taskPeriodEntity, vo);
                } catch (IllegalAccessException | InvocationTargetException e) {
                    throw new RuntimeException(e);
                }
                taskPeriodEntity.setExecutePeriodNum("2");
                taskPeriodEntity.setExecuteStime(exeSTime);
                taskPeriodEntity.setExecuteEtime(exeETime);
                taskPeriodEntity.setCreatTime(DateUtil.now());
//                taskPeriodEntity.setExecuteTaskNo(GenTaskNoTool.createTaskNo());

                vo.setTaskName(taskName + "-周期内-" + 1);

                taskEntities.add(vo);
                taskPeriodEntities.add(taskPeriodEntity);
            }
        });
        doInsertV2(taskEntities, taskOperateEntities, taskPeriodEntities);
        return null;
    }


    /**
     * 实际执行插入巡视工单的方法
     *
     * @param taskVos
     * @param taskOperateEntities
     * @param taskPeriodEntities
     * @return int
     * @version 2.0
     */
    private int doInsertV2(List<EnPatrolTaskEntity> taskVos, List<EnPatrolTaskOperateEntity> taskOperateEntities, List<EnPatrolTaskPeriodEntity> taskPeriodEntities) {
        //取出巡视目标的信息
        ArrayList<EnPatrolTaskEquipEntity> temp = new ArrayList<>();
        taskVos.forEach(taskVo -> {
            taskVo.getEquipList().forEach(equip -> {
                equip.setTaskNo(taskVo.getTaskNo());
                equip.setIsDel("0");
                temp.add(equip);
            });
        });
        //插入
        boolean b = this.saveBatch(taskVos);
        boolean c = taskEquipService.saveBatch(temp);
        taskOperateService.saveBatch(taskOperateEntities);
        taskPeriodService.saveBatch(taskPeriodEntities);

        return BooleanUtil.toInt(b && c);
    }

    @Override
    public int update(List<EnPatrolTaskVo> forms) {
        List<EnPatrolTaskEntity> entitys = mapstruct.toEntitys(forms);
        int result = 0;
        for (EnPatrolTaskEntity entity : entitys) {
            if ("99".equals(entity.getPTaskStatusNo()) && "1".equals(entity.getAppraiseStatus())) {
                // 归档操作并且合格，插入操作记录
                this.saveTaskOperate(mapstruct.toVo(entity), "99", "归档");
                entity.setPTaskStatusNo("99");
                entity.setPTaskStatusName("归档");
            } else if ("99".equals(entity.getPTaskStatusNo()) && "2".equals(entity.getAppraiseStatus())) {
                // 归档操作但不合格，回退到接单环节
                this.saveTaskOperate(mapstruct.toVo(entity), "15", "质量评价不合格");
                entity.setPTaskStatusNo("15");
                entity.setPTaskStatusName("已接单");
                entity.setATaskStatusName("退单");
                entity.setATaskStatusNo("3");
            } else {//删除或编辑接口
                //第一步删除巡视工单关联的设备
                MPJLambdaWrapper<EnPatrolTaskEquipEntity> queryWrapper = new MPJLambdaWrapper<>();
                /** todo getPsrId-> todo-must�޸�Ϊ��¼�������ֶ�todo */
                queryWrapper.eq(EnPatrolTaskEquipEntity::getTaskNo, entity.getTaskNo());
                queryWrapper.selectAll(EnPatrolTaskEquipEntity.class);
                List<EnPatrolTaskEquipEntity> entitiesOld = equipMapper.selectList(queryWrapper);
                entitiesOld.forEach(equipOld -> {
                    equipOld.setIsDel("1");
                });
                boolean oldequip = taskEquipService.updateBatchById(entitiesOld);
                //第二步保存巡视工单关联的设备
                ArrayList<EnPatrolTaskEquipEntity> temp = new ArrayList<>();
                entity.getEquipList().forEach(equip -> {
                    equip.setTaskNo(entity.getTaskNo());
                    equip.setIsDel("0");
                    equip.setId("");
                    temp.add(equip);
                });
                //插入
                boolean c = taskEquipService.saveBatch(temp);
            }
            EnPatrolTaskPeriodEntity temp = new EnPatrolTaskPeriodEntity();
            try {
                BeanUtils.copyProperties(temp, entity);
            } catch (IllegalAccessException | InvocationTargetException e) {
                throw new RuntimeException(e);
            }
            LambdaUpdateWrapper<EnPatrolTaskPeriodEntity> updateWrapper = Wrappers
                    .lambdaUpdate(EnPatrolTaskPeriodEntity.class)
                    .eq(temp.getId() != null, EnPatrolTaskPeriodEntity::getId, temp.getId())
                    //.or()
                    .eq(temp.getTaskNo() != null, EnPatrolTaskPeriodEntity::getTaskNo, temp.getTaskNo())
                    .eq(EnPatrolTaskPeriodEntity::getIsDel, "0");
            LambdaUpdateWrapper<EnPatrolTaskEntity> taskWrapper = Wrappers
                    .lambdaUpdate(EnPatrolTaskEntity.class)
                    .eq(temp.getId() != null, EnPatrolTaskEntity::getId, temp.getId())
                    //.or()
                    .eq(temp.getTaskNo() != null, EnPatrolTaskEntity::getTaskNo, temp.getTaskNo())
                    .eq(EnPatrolTaskEntity::getIsDel, "0");
            taskPeriodService.update(temp, updateWrapper);
//            result += baseMapper.updateById(entity);
            result += baseMapper.update(entity, taskWrapper);
        }
        return result;
    }

    /**
     * 保存任务操作
     *
     * @param taskVo        taskVo
     * @param optStatus     optStatus
     * @param optStatusName optStatusName
     */
    public void saveTaskOperate(EnPatrolTaskVo taskVo, String optStatus, String optStatusName) {
        EnPatrolTaskOperateEntity operateEntity = new EnPatrolTaskOperateEntity();
        operateEntity.setTaskNo(taskVo.getTaskNo());
        operateEntity.setOptStatus(optStatus);
        operateEntity.setOptStatusName(optStatusName);
        operateEntity.setOptTime(new Date());

        taskOperateMapper.insert(operateEntity);
    }

    /**
     * 定时任务调用时,同步创建巡视工单
     *
     * @param po
     * @return
     */
    @Override
    @Transactional
    public boolean createPatrolTask(PatrolTaskPo po) {

        boolean a = this.taskPeriodService.updateBatchById(po.getUpdateTaskPeriodEntities());
        boolean b = this.taskPeriodService.saveBatch(po.getInsertTaskPeriodEntities());
        boolean c = this.saveBatch(po.getInsertTaskEntities());
        boolean d = this.updateBatchById(po.getUpdateTaskEntities());
        boolean e = this.taskOperateService.saveBatch(po.getOperateEntities());
        boolean h = this.taskEquipService.saveBatch(po.getTaskEquipEntities());

        return a && b && c && d && e && e && h;
    }
}
